#pragma once

#include "../../jsonxx/json.hpp"
#include "ast.hpp"

using namespace jsonxx;

template <> struct json_bind<PtrASTNode> {
    const string NAME = "Name";
    const string CHILDREN = "children";
    void to_json(json &j, const PtrASTNode &ast) {
        jsonxx::to_json(j[NAME], ast->name);
        for (auto [key, val] : ast->fields) {
            string str;
            for (auto j : val)
                str += j.word;
            jsonxx::to_json(j[key], str);
        }
        vector<json> children;
        for (auto i = ast->children.begin(); i != ast->children.end(); ++i) {
            json tmp;
            to_json(tmp, *i);
            children.push_back(tmp);
        }
        if (!children.empty())
            j[CHILDREN] = children;
    }

    void from_json(const json &j, PtrASTNode &ast) {
        jsonxx::from_json(j[NAME], ast->name);
        vector<json> children;
        if (j.count(CHILDREN))
            children = j[CHILDREN].as_array();
        for (auto i : children) {
            PtrASTNode tmp = make_shared<ASTNode>();
            from_json(i, tmp);
            ast->children.push_back(tmp);
        }
        for (auto [key, val] : j.as_object()) {
            if (key != CHILDREN) { // 处理fields
                Token token;
                token.word = val.as_string();
                ast->fields[key].push_back(token);
            }
        }
    }
};
